package extension.room.phom;

import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;
import extension.game.room.Game;
import extension.game.room.Player;
import extension.game.zone.Flag;
import extension.room.analyse.Card;
import java.util.LinkedList;
import java.util.List;
import log.Debug;

/**
 *
 * @author daz
 */
public class PhomGame extends Game implements Runnable {

    public static final int HAVE_PHOM = 0;
    public static final int NOT_HAVE_PHOM = 1;
    private PhomResponse phomResponse;
    private int lastFight;
    private boolean isFinishRound;
    private int cardFight;
    private int canEat;
    private int showPhomOrder;
    public static int numberCardFinish = 4;
    private boolean canGetDrawCard;
    private int isChargePenalty;
    private boolean isLastRound;
    private int numberShowPhom;
    private PhomPlayer[] listPlayers;
    private PhomExtension phomExtension;
    private boolean isGenerate;

    PhomGame(PhomExtension phomExtension, int roomId) {
        super(phomExtension.getParentRoom(), roomId);
        this.phomExtension = phomExtension;
        canGetDrawCard = true;
        numberDealCard = 9;
        listPlayers = new PhomPlayer[maxPlayer];
        this.phomResponse = phomExtension.getResponse();
        if (Debug.isDebug) {
            numberCardFinish = 4;
            betMoney = 100;
        }
    }

    @Override
    public PhomPlayer[] getListPlayers() {
        return listPlayers;
    }

    @Override
    public PhomPlayer addPlayer(String name, long money, User user) {
        PhomPlayer player = new PhomPlayer(name, money, numberPlayers);
        player.setUser(user);
        if (numberPlayings <= 0 || numberPlayers <= 0) {
            isPlay = false;
        }
        if (numberPlayers < maxPlayer) {
            int seatPos = -1;
            for (int i = 0; i < maxPlayer; i++) {
                if (listPlayers[i] == null) {
                    seatPos = i;
                    listPlayers[seatPos] = player;
                    listPlayers[seatPos].setSeatPos(seatPos);
                    if (isPlay) {
                        listPlayers[seatPos].setState(PhomPlayer.NOT_READY);
                    } else {
                        numberPlayings++;
                    }
                    break;
                }
            }
            if (numberPlayings == 1 && seatPos > -1) {
                listPlayers[seatPos].isHost = true;
                tableHost = seatPos;
            }
            numberPlayers++;
        } else {
//            listViews.add(player);
            player.setSeatPos(-1);
        }
        if (!isPlay && listPlayers[tableHost] == null) {
            for (int i = 0; i < maxPlayer; i++) {
                if (listPlayers[i] != null) {
                    listPlayers[i].isHost = true;
                    tableHost = i;
                    break;
                }
            }
        }
        addTableInfo();
        Debug.d("number playing when add:" + numberPlayings);
        return player;
    }

    @Override
    protected void addTableInfo() {
        List<String> listPlayerNames = new LinkedList<String>();
        List<Integer> listPlayerPositions = new LinkedList<Integer>();
        for (int i = 0; i < listPlayers.length; i++) {
            if (listPlayers[i] != null) {
                if (listPlayers[i].getState() != PhomPlayer.PLAYING) {
                    listPlayerPositions.add(0);
                } else {
                    listPlayerPositions.add(1);
                }
                listPlayerNames.add(listPlayers[i].getName());
            } else {
                listPlayerPositions.add(-1);
                listPlayerNames.add("0");
            }
        }

        room.setProperty(Flag.NUMBER_PLAYER, numberPlayings);
        room.setProperty(Flag.ROOM_PLAYER_NAME, listPlayerNames);
        room.setProperty(Flag.ROOM_PLAYER_POS, listPlayerPositions);
        Room lobbyRoom = phomExtension.getParentZone().getRoomByName("The Lobby");
        List<User> listSend = lobbyRoom.getUserList();
        for (User u : listSend) {
            String groupView = (String) u.getProperty(Flag.GROUP_NAME);
            if (groupView.equals(room.getGroupId())) {
                phomResponse.sendTableInfo(room.getName(), listPlayerNames, listPlayerPositions, lobbyRoom.getUserList());
            }
        }

    }

    private void reset() {
        penaltyMoney = 0;
        isLastRound = false;
        gameTurn = 0;
        isPlay = false;
        lastFight = -1;
        cardFight = -1;
        numberPlayings = 0;
        isChargePenalty = -1;
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null) {
                listPlayers[i].setState(PhomPlayer.NOT_READY);
                listPlayers[i].resetCard();
                numberPlayings++;
            }
        }
        Debug.d("number playing when reset :" + numberPlayings);
        canGetDrawCard = true;
    }

    @Override
    public long removePlayer(int leaveId) {
        long playerMoney = 0;
        numberPlayers--;
        if (listPlayers[leaveId] != null) {
            if ((listPlayers[leaveId].getState() == PhomPlayer.PLAYING && isPlay)
                    || (!isPlay)) {
                listPlayers[leaveId].updateMoney(-betMoney * 5);
                playerMoney = listPlayers[leaveId].getMoney() + listPlayers[leaveId].getTotalMoney();
                listPlayers[leaveId] = null;
                numberPlayings--;
                Debug.d("number playing when remove :" + numberPlayings);
                if (leaveId == tableHost) {
                    updateTableHost();
                }
                if (isPlay) {
                    penaltyMoney += betMoney * 5;
                    if (gameTurn == leaveId) {
                        nextTurn();
                    }
                    if (numberPlayings < 2) {
                        onFinishMatch();
                    }
                } else {
                    int numberReadys = 0;
                    for (int i = 0; i < maxPlayer; i++) {
                        if (listPlayers[i] != null && listPlayers[i].getState() == PhomPlayer.READY) {
                            numberReadys++;
                        }
                    }
                    if (numberReadys == numberPlayings) {
                        startGame();
                    } else if (numberReadys == numberPlayers - 1) {
                        setIsHostTimeOut(true);
                        phomResponse.sendTimeCount(tableHost);
                    }
                }
                if (numberPlayers <= 0) {
                    resetAllTable();
                }

            } else {
                playerMoney = listPlayers[leaveId].getMoney() + listPlayers[leaveId].getTotalMoney();
                listPlayers[leaveId] = null;
            }

        }
        addTableInfo();
        return playerMoney;
    }

    @Override
    public void updateTableHost() {
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null) {
                tableHost = i;
                listPlayers[i].isHost = true;
                if (isPlay) {
                    phomResponse.sendUpdateTableHost(i, 1);
                } else {
                    phomResponse.sendUpdateTableHost(i, 0);
                    updateReadyState();
                }
                break;
            }
        }
    }

    private void resetAllTable() {
        winnerId = -1;
        betMoney = betMin;
    }

    @Override
    public void run() {
        while (isRunning) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
            }
        }
    }

    @Override
    public int changePlayerState(int readyId) {
        if (listPlayers[readyId] != null) {
            return listPlayers[readyId].changeState();
        }
        return -1;
    }

    @Override
    public void dealCard() {
        gameTurn = -1;
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null && listPlayers[i].isHost) {
                gameTurn = i;
                break;
            }
        }
        showPhomOrder = 0;
        dealer.shuffleCard();
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null) {
                if (listPlayers[i].getState() == PhomPlayer.READY) {
                    listPlayers[i].resetCard();
                    for (int j = 0; j < numberDealCard; j++) {
                        listPlayers[i].addCard(getCard(), PhomPlayer.NORMAL_CARD);
                    }
                }
            }
        }
        if (winnerId > -1 && winnerId < maxPlayer && listPlayers[winnerId] != null) {
            listPlayers[winnerId].addCard(getCard(), PhomPlayer.NORMAL_CARD);
            gameTurn = winnerId;
        } else if (gameTurn > -1 && gameTurn < maxPlayer && listPlayers[gameTurn] != null) {
            listPlayers[gameTurn].addCard(getCard(), PhomPlayer.NORMAL_CARD);
        } else {
            for (int i = 0; i < maxPlayer; i++) {
                if (listPlayers[i] != null) {
                    listPlayers[i].addCard(getCard(), PhomPlayer.NORMAL_CARD);
                    gameTurn = i;
                    break;
                }
            }
        }
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null) {
                if (listPlayers[i].getState() == PhomPlayer.READY) {
                    listPlayers[i].generateListPhom();
                    listPlayers[i].setState(PhomPlayer.PLAYING);
                    phomResponse.sendDealCard(listPlayers[i].getListCardIds(), listPlayers[i].getListPhom(), listPlayers[i].getUser());
                }
            }
        }
//        Debug.i("first turn :" + listPlayers[gameTurn].getName());
//        phomResponse.sendFirstTurn(gameTurn, phomExtension.getParentRoom().getUserList());
    }

    private int getCard() {
        int cardId = dealer.nextCard();
        if (cardId == -1) {
            for (int i = 0; i < maxPlayer; i++) {
                if (listPlayers[i] != null) {
                    phomExtension.getApi().kickUser(listPlayers[i].getUser(), null, "", 0);
                    Debug.d("out of dealer index of phom");
                    listPlayers[i] = null;
                }

            }
            onFinishMatch();
        }
        return cardId;
    }

    @Override
    public void nextTurn() {
        if (isPlay) {
            isChargePenalty = -1;
            numberShowPhom = 0;
            int numberLastRound = 0;
            for (int i = 0; i < maxPlayer; i++) {
                if (listPlayers[i] != null) {
//                    Debug.d(listPlayers[i].getName() + ":state:" + listPlayers[i].getState() + ",");
                    if (listPlayers[i].getState() == PhomPlayer.PLAYING) {
                        if (listPlayers[i].getNumberCardFights() >= numberCardFinish) {
                            numberShowPhom++;
                        } else if (listPlayers[i].getNumberCardFights() >= numberCardFinish - 1) {
                            numberLastRound++;
                        }
                    }
                }
            }
//            Debug.d("number show phom next turn :" + numberShowPhom);
            if (numberLastRound == numberPlayings) {
                isLastRound = true;
            }
            if (numberShowPhom == numberPlayings) {
                onFinishMatch();
                return;
            }
            lastFight = gameTurn;
            for (int i = gameTurn + 1; i < maxPlayer + gameTurn; i++) {
                if (listPlayers[i % maxPlayer] != null && listPlayers[i % maxPlayer].getState() == PhomPlayer.PLAYING) {
                    gameTurn = i % maxPlayer;
                    break;
                }
            }
            sendFightTurn();
            canGetDrawCard = true;
            isGenerate = false;
        }
    }

    private void sendFightTurn() {
        canEat = listPlayers[gameTurn].checkEatCard(cardFight);
        //check eat card
        phomResponse.sendGameTurn(gameTurn, cardFight, lastFight, canEat);
    }

    public boolean getIsFinishRound() {
        return isFinishRound;
    }

    public void removeCardInHand(int cardFight) {
        listPlayers[gameTurn].removeCardInHand(cardFight);

    }

    public void skipTurn(int skipId) {
    }

    public boolean isCanGetDrawCard() {
        return canGetDrawCard;
    }

    public int getDrawCard() {
        if (!isGenerate) {
            int cardGenerate = getCard();
            listPlayers[gameTurn].addCard(cardGenerate, PhomPlayer.NORMAL_CARD);
            isGenerate = true;
            return cardGenerate;
        }
        return -1;
    }

    public PhomPlayer getPlayerFight() {
        return listPlayers[gameTurn];
    }

    private void sumPlayerPoint() {
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null && listPlayers[i].getState() == PhomPlayer.PLAYING) {
                if (listPlayers[i].getHavePhom() == 1) {
                    listPlayers[i].sumPoint();
                }
            }
        }
    }

    private void rankPlayer() {
        int[] rank = new int[]{0, 1, 2, 3};
        int[] totalPoint = new int[maxPlayer];
        int[] showPhomOrderArr = new int[maxPlayer];

        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null && listPlayers[i].getState() == PhomPlayer.PLAYING) {
                totalPoint[i] = listPlayers[i].getTotalPoint();
                showPhomOrderArr[i] = listPlayers[i].getShowPhomOrder();
            } else {
                totalPoint[i] = 100 + i;
                showPhomOrderArr[i] = 100 + i;
            }
        }

        for (int i = 0; i < maxPlayer - 1; i++) {
            for (int j = i + 1; j < maxPlayer; j++) {
                if ((totalPoint[i] > totalPoint[j])
                        || (totalPoint[i] == totalPoint[j] && showPhomOrderArr[i] > showPhomOrderArr[j])) {
                    int temp = rank[i];
                    rank[i] = rank[j];
                    rank[j] = temp;
                    temp = totalPoint[j];
                    totalPoint[j] = totalPoint[i];
                    totalPoint[i] = temp;
                }
            }
        }


        int count = 0;
        for (int i = 0; i < maxPlayer; i++) {
            int seat = rank[i];
            if (seat < maxPlayer && seat >= 0 && listPlayers[seat] != null) {
                listPlayers[seat].setRank(count);
//                Debug.d(listPlayers[seat].getName() + ":" + count + ",point :" + listPlayers[i].getTotalPoint());
                count++;
            }
        }
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null && listPlayers[i].getState() == PhomPlayer.PLAYING) {
                Debug.d(listPlayers[i].getName() + ":" + listPlayers[i].getRank() + ",point :" + listPlayers[i].getTotalPoint());
                count++;
            }
        }
    }

    private void logShowPhom(String name, List<Integer> listPhom) {
        if (listPhom != null && !listPhom.isEmpty()) {
            StringBuilder builder = new StringBuilder();
            for (Integer card : listPhom) {
                builder.append(Card.getName(card));
                builder.append(",");
            }
            Debug.d(name + "-show phom:" + builder.toString());
        } else {
            Debug.d(name + "-show phom: not have phom");
        }
    }

    private void sendPlayerCard() {
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null && listPlayers[i].getState() == PhomPlayer.PLAYING) {
                logShowPhom(listPlayers[i].getName(), listPlayers[i].getListCardIds());
                phomResponse.sendPlayerCard(listPlayers[i]);
            }
        }

    }

    private void calculateMoneyChange() {
        winnerId = 0;
        int totalMoneyChange = 0;
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null && listPlayers[i].getState() == PhomPlayer.PLAYING) {
                int rank = listPlayers[i].getRank();
                Debug.d(listPlayers[i].getName() + ": money=" + listPlayers[i].getMoney());
                if (rank == 0) {
                    winnerId = i;
                } else {
                    if (listPlayers[i].getHavePhom() == 1) {
                        totalMoneyChange += betMoney * rank;
                        listPlayers[i].setMoneyChange(-betMoney * rank);
                    } else {
                        listPlayers[i].setMoneyChange(-betMoney * 4);
                        totalMoneyChange += betMoney * 4;
                    }
                }
            }
        }
        if (winnerId >= 0 && listPlayers[winnerId] != null) {
//            Debug.d(listPlayers[winnerId].getName() + ": money=" + listPlayers[winnerId].getMoney());
            totalMoneyChange += penaltyMoney;
            listPlayers[winnerId].setMoneyChange(totalMoneyChange);
        }
    }

    private void onFinishMatch() {
        Debug.i("on finish match");
        //
        sendPlayerCard();
        sumPlayerPoint();
        rankPlayer();
        calculateMoneyChange();
        //
        List<Integer> havePhom = new LinkedList<Integer>();
        List<Long> moneyResult = new LinkedList<Long>();
        List<Integer> rank = new LinkedList<Integer>();
        List<Long> listPlayerMoney = new LinkedList<Long>();

        int count = 0;
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null && listPlayers[i].getState() == PhomPlayer.PLAYING) {
                listPlayers[i].updateMoneyChange();
                havePhom.add(listPlayers[i].getHavePhom());
                moneyResult.add(listPlayers[i].getMoneyChange());
                listPlayerMoney.add(listPlayers[i].getMoney());
                rank.add(listPlayers[i].getRank());
                if (listPlayers[i].getRank() == 0) {
                    winnerId = i;
                }
                count++;
            } else {
                havePhom.add(-1);
                moneyResult.add(0l);
                rank.add(-1);
                listPlayerMoney.add(-1l);
            }
        }
        phomResponse.sendMatchFinish(havePhom, rank, moneyResult, listPlayerMoney, tableHost);
        updateDatabase();
        reset();
        checkAllowPlay();
    }

    private void calculateMoneyU() {
        winnerId = gameTurn;
        int totalMoneyChange = 0;
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null && listPlayers[i].getState() == PhomPlayer.PLAYING) {
                long moneyChange = 0;
                if (i != winnerId) {
                    if (isChargePenalty == -1) {
                        moneyChange = betMoney * 5;
                    } else {
                        if (listPlayers[isChargePenalty].getNumberLostCard() >= 3) {
                            if (i == isChargePenalty) {
                                moneyChange = betMoney * (numberPlayings - 1) * 5;
                            } else {
                                moneyChange = 0;
                            }
                        } else if (listPlayers[winnerId].getPenaltyCreatMoreTurn() == i && i != winnerId) {
                            moneyChange = betMoney * (numberPlayings - 1) * 5;
                        }
                    }
                    listPlayers[i].setMoneyChange(-moneyChange);
                }
                totalMoneyChange += moneyChange;

            }
        }
        Debug.d(listPlayers[winnerId].getName() + ": money=" + listPlayers[winnerId].getMoney());
        totalMoneyChange += penaltyMoney;
        listPlayers[winnerId].setMoneyChange(totalMoneyChange);
    }

    public void onFinishU(int type) {
        calculateMoneyU();
        //type =0 have phom
        //type 1 not have phom
        isPlay = false;
        List<Long> moneyResult = new LinkedList<Long>();
        List<Long> listPlayerMoney = new LinkedList<Long>();
        int count = 0;
        winnerId = gameTurn;
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null && listPlayers[i].getState() == PhomPlayer.PLAYING) {
                listPlayers[i].updateMoneyChange();
                moneyResult.add(listPlayers[i].getMoneyChange());
                listPlayerMoney.add(listPlayers[i].getMoney());
                count++;
            } else {
                moneyResult.add(0l);
                listPlayerMoney.add(-1l);
            }
        }

        if (type == 0) {
            phomResponse.sendPhomU(listPlayers[gameTurn].getListPhom(), gameTurn, moneyResult, listPlayerMoney, tableHost);
        } else {
            phomResponse.sendPhomU(gameTurn, moneyResult, listPlayerMoney, tableHost);
        }
        StringBuilder builder = new StringBuilder();
        for (Integer card : listPlayers[gameTurn].getListPhom()) {
            builder.append(Card.getName(card));
            builder.append(",");
        }
        Debug.d(listPlayers[gameTurn].getName() + " u:" + builder.toString());
        updateDatabase();
        reset();
        checkAllowPlay();
    }

    public void setCardFight(int cardFight) {
        this.cardFight = cardFight;
    }

    public void eatCard() {
        isGenerate = true;
        canGetDrawCard = false;
        Debug.d("is last round :" + isLastRound);
        listPlayers[lastFight].updateFightedCard(-1);
        listPlayers[gameTurn].addCard(cardFight, PhomPlayer.EAT_CARD);
        int transferPos = -1;

        for (int i = gameTurn; i < (gameTurn + maxPlayer); i++) {
            int pos = i % maxPlayer;
            if (listPlayers[pos] != null) {
                if (listPlayers[pos].getNumberCardFights() > listPlayers[lastFight].getNumberCardFights()) {
                    int cardRemove = listPlayers[pos].updateFightedCard(-1);
                    if (cardRemove >= 0) {
                        listPlayers[lastFight].addFightedCard(cardRemove);
                    }
                    transferPos = pos;
                    break;
                }
            }
        }

        if (transferPos != -1) {
            listPlayers[transferPos].moreFightTurn();
            if (listPlayers[transferPos].getNumberCardFights() == numberCardFinish - 1) {
                listPlayers[transferPos].setPenaltyCreatMoreTurn(gameTurn);
            }
            Debug.d(listPlayers[transferPos].getName() + " tranfer card :" + listPlayers[transferPos].getNumberCardFights());
            Debug.d(listPlayers[lastFight].getName() + " tranfer card :" + listPlayers[lastFight].getNumberCardFights());
            phomResponse.sendTransferCard(transferPos, lastFight, gameTurn);
        } else {
            listPlayers[lastFight].moreFightTurn();
        }

        long moneyChange = betMoney;
        listPlayers[lastFight].updateLostCard();

        if (listPlayers[lastFight].getNumberLostCard() >= 3) {
            isChargePenalty = lastFight;
        }
        if (isLastRound) {
            moneyChange = betMoney * 4;
        }
        listPlayers[gameTurn].updateMoney(moneyChange);
        listPlayers[lastFight].updateMoney(-moneyChange);

        phomResponse.sendMoneyChange(moneyChange, listPlayers[gameTurn].getSeatPos(), listPlayers[gameTurn].getMoney(),
                listPlayers[lastFight].getSeatPos(), listPlayers[lastFight].getMoney());
        updateDatabase();
    }

    public int getCardFight() {
        return cardFight;
    }

    public void setLastShowPhom() {
        listPlayers[gameTurn].setShowPhomOrder(showPhomOrder);
        showPhomOrder++;

    }

    public int getCanEat() {
        return canEat;
    }

    public int getLastFight() {
        return lastFight;
    }

    public int getShowPhomOrder() {
        return showPhomOrder;
    }

    public void depositAction() {
        if (listPlayers[gameTurn].getHavePhom() == 1) {
            listPlayers[gameTurn].resetDeposit();
            for (int i = 0; i < maxPlayer; i++) {
                if (gameTurn != i
                        && listPlayers[i] != null
                        && listPlayers[i].getShowPhomOrder() >= 0) {
                    listPlayers[gameTurn].generateDepositCard(listPlayers[i].getListSetFinal(), listPlayers[i].getSeatPos());
                }
            }
        }
        phomResponse.notifyDeposit(listPlayers[gameTurn].getSeatPos(), listPlayers[gameTurn].getListDepositCard(),
                listPlayers[gameTurn].getListDepositTarget(), listPlayers[gameTurn].getUser());
    }

    public void depositCard() {
        List<Integer> listDeposit = listPlayers[gameTurn].getListDepositCard();
        List<Integer> listTarget = listPlayers[gameTurn].getListDepositTarget();
        for (int i = 0; i < listDeposit.size(); i++) {
            listPlayers[gameTurn].removeCardInHand(listDeposit.get(i));
        }
        for (Integer target : listTarget) {
            listPlayers[target].addToPhom(listDeposit);
        }
    }

    public int getNumberCardFinish() {
        return numberCardFinish;
    }

    @Override
    public boolean canHostReady() {
        int numberReadys = 0;
        if (numberPlayings == 1) {
            return false;
        }
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null && listPlayers[i].getState() == PhomPlayer.READY) {
                numberReadys++;
            }
        }
        if (numberReadys == numberPlayings - 1) {
            return true;
        }
        return false;
    }

    @Override
    public void updateDatabase() {
        if (!Debug.isDebug) {
            for (int i = 0; i < maxPlayer; i++) {
                if (listPlayers[i] != null) {
                    phomExtension.getDatabase().updateMoneyJoin(phomExtension.getRoomPrefix(), listPlayers[i].getName(), listPlayers[i].getMoney());
                }
            }
        }

    }

    @Override
    protected void sendTableInfo(String roomName, List<String> listNames, List<Integer> listPos, List<User> listUser) {
        this.phomResponse.sendTableInfo(roomName, listNames, listPos, listUser);
    }

    @Override
    public void sendTimeCount(int host) {
        this.phomResponse.sendTimeCount(host);
    }

    @Override
    public void sendUpdateTableHost(int newHost, int isContinue) {
        this.phomResponse.sendUpdateTableHost(newHost, isContinue);
    }

    @Override
    protected void sendPlayerKick(String name, int seatPos, User user) {
        this.phomResponse.sendPlayerKick(name, seatPos, user);
    }

    @Override
    public int countNumberReady() {
        int result = 0;
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null && listPlayers[i].getState() == PhomPlayer.READY) {
                result++;
            }
        }
        return result;
    }

    @Override
    protected void checkAllowPlay() {
        if (!Debug.isDebug) {
            for (int i = 0; i < maxPlayer; i++) {
                if (listPlayers[i] != null && listPlayers[i].getMoney() < betMoney * 5) {
                    phomResponse.sendPlayerKick(listPlayers[i].getName(), listPlayers[i].getSeatPos(), listPlayers[i].getUser());
//                removePlayer(i);
                }
            }
        } else {
            for (int i = 0; i < maxPlayer; i++) {
                if (listPlayers[i] != null && listPlayers[i].getMoney() < 0) {
                    phomResponse.sendPlayerKick(listPlayers[i].getName(), listPlayers[i].getSeatPos(), listPlayers[i].getUser());
//                removePlayer(i);
                }
            }
        }
    }

    @Override
    public void updateReadyState() {
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null && listPlayers[i].getState() == PhomPlayer.READY) {
                listPlayers[i].setState(PhomPlayer.NOT_READY);
                phomResponse.sendReadyState(i, PhomPlayer.NOT_READY, 1);
            }
        }
    }

    @Override
    public void sendTableInfo(List<String> listNames, List<Long> listMoneys, List<Integer> listStates, Player player, User user) {
        phomResponse.sendTableInfo(listNames, listMoneys, listStates, betMoney,
                isPlay, tableHost, player.getSeatPos(), player.getTotalMoney(), user);
        if (isPlay) {
            for (int i = 0; i < maxPlayer; i++) {
                PhomPlayer p = listPlayers[i];
                if (p != null && p.getState() == PhomPlayer.PLAYING) {
                    if (p.getShowPhomOrder() >= 0) {
                        phomResponse.sendTableState(p.getListEatCards(), p.getListFightCard(), p.getSeatPos(), p.getListPhom(), user);
                    } else {
                        phomResponse.sendTableState(p.getListEatCards(), p.getListFightCard(), p.getSeatPos(), null, user);
                    }
                }
            }
        } else {
            if (isHostTimeOut) {
                phomResponse.sendDeleteHostTimeOut(tableHost);
                setIsHostTimeOut(false);
            }
        }
    }

    @Override
    public void doLoop() {
    }

    @Override
    public void doReady() {
        setIsHostTimeOut(true);
        phomResponse.sendTimeCount(tableHost);
    }

    @Override
    public void updateTableInfo(List<String> listNames, List<Long> listMoneys, List<Integer> listStates, Player player) {
        sendTableInfo(listNames, listMoneys, listStates, player, player.getUser());

        if (numberPlayings >= 1 && player.getSeatPos() >= 0) {
            sendUpdateTable(player.getUser(), player);
            sendUpdate();
        }
    }

    private void sendUpdateTable(User user, Player player) {
        List<User> listSend = room.getUserList();
        listSend.remove(user);
        phomResponse.sendUpdatePlayers(user.getName(), player.getMoney(), player.getSeatPos(), listSend);
    }

    private void sendUpdate() {
        String groupName = room.getGroupId();
        Room lobbyRoom = phomExtension.getParentZone().getRoomByName("The Lobby");
        List<User> listSend = lobbyRoom.getUserList();
        for (User u : listSend) {
            String groupView = (String) u.getProperty(Flag.GROUP_NAME);
            if (groupView.equals(groupName)) {
                phomResponse.sendUpdateTable(room.getName(), numberPlayings, room.getGroupId(), betMoney, u);
            }
        }
    }

    @Override
    public void updateNumberPlaying() {
        numberPlayings = 0;
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null) {
                numberPlayings++;
            }
        }
    }

    @Override
    public void updateNumberInRoom() {
        numberInRooms = 0;
        for (int i = 0; i < maxPlayer; i++) {
            if (listPlayers[i] != null) {
                numberInRooms++;
            }
        }
    }
}
